package com.tinyideatech.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.wxpay.sdk.WXPayUtil;
import com.tinyideatech.common.utils.DateUtils;
import com.tinyideatech.common.utils.RedisUtil;
import com.tinyideatech.common.utils.http.HttpClientUtil;
import com.tinyideatech.system.entity.CarDevice;
import com.tinyideatech.system.entity.CarRmonOrder;
import com.tinyideatech.system.mapper.CarDeviceMapper;
import com.tinyideatech.system.mapper.CarRmonOrderMapper;
import com.tinyideatech.system.service.ICarGoodsService;
import com.tinyideatech.system.service.ICarRmonOrderService;
import org.apache.http.NameValuePair;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhangy-5
 * @date 2019-12-15
 */
@Service
public class CarRmonOrderServiceImpl extends ServiceImpl<CarRmonOrderMapper, CarRmonOrder>
        implements ICarRmonOrderService {
    private static List<String> wxPayCache = new ArrayList<String>();

    @Autowired
    private RedisUtil redisUtil;

    private static final Logger logger = LoggerFactory.getLogger(CarRmonOrderServiceImpl.class);

    private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss",
            "yyyy.MM.dd HH:mm", "yyyy.MM", "yyyyMMddHHmmss"};

    private static final String URL = "http://47.104.142.111:8081/";

    @Value("${wx.pay.mchKey}")
    private String key;

    @Value("${ftp.host}")
    private String ftpHost;

    @Value("${ftp.catalog}")
    private String ftpCatalog;

    @Value("${ftp.imgTargetDir}")
    private String imgTargetDir;

    @Value("${url.xinyao}")
    private String xinyaoServiceUrl;

    @Autowired
    private CarDeviceMapper carDeviceMapper;

    @Autowired
    private ICarGoodsService goodsService;

    @Autowired
    private CarRmonOrderMapper carRmonOrderMapper;

    @Override
    public String ip(HttpServletRequest request) {

        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.contains(",")) {
                ip = ip.split(",")[0];
            }
        }

        return ip;
    }

    @Override
    public boolean verifyWxPayUnifiedOrderResult(WxPayUnifiedOrderResult result, String deviceId, String outTradeNo,
                                                 String expireTime) {
        if (result == null) {
            logger.error("请求出错");
            return false;
        }
        try {
            // 更新code和device之间的关系
            CarDevice carDevice = carDeviceMapper.selectAllById(deviceId);
            if (carDevice == null) {
                // 如果这个没有绑定关系
                carDevice = new CarDevice();
                carDevice.setDeviceId(deviceId);
                carDevice.setCreateBy("admin");
                carDevice.setCreateTime(DateUtils.getNowDate());
                carDevice.setDeviceProperties("测试");
                carDeviceMapper.insert(carDevice);
                return parseOrder(result, deviceId, outTradeNo, expireTime);
            } else {
                // 2019-11-15 修改登录逻辑
                if (carDevice.getDeviceRmon() == null || carDevice.getDeviceRmon().equals(0)) {
                    carDevice.setDeviceRmon(0);
                    carDeviceMapper.updateById(carDevice);
                }
                return parseOrder(result, deviceId, outTradeNo, expireTime);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return false;
    }

    private boolean parseOrder(WxPayUnifiedOrderResult result, String deviceId, String outTradeNo, String expireTime) {
        // 预支付订单
        CarRmonOrder preOrder = new CarRmonOrder();
        logger.info(String.format("[rmon订单处理:%s]", result));
        preOrder.setPrepayId(result.getPrepayId());
        preOrder.setDeviceId(deviceId);
        preOrder.setCreateTime(DateUtils.getNowDate());
        preOrder.setTotalPrice(goodsService.getPrice(4));
        preOrder.setOrderId(outTradeNo);
        preOrder.setTimeEnd(DateUtils.parseDate(expireTime));
        String codeUrlFtp = getFullPathImgFtp() + "wx" + outTradeNo + ".png";
        preOrder.setQrcodeUrl(codeUrlFtp);
        int orderInsert = carRmonOrderMapper.insert(preOrder);
        if (orderInsert == 1) {
            logger.info(String.format("rmon插入值为[%s]", preOrder));
            return true;
        }
        return false;
    }

    /**
     * 微信支付回调处理
     *
     * @param orderNotifyResult
     * @return
     * @throws Exception
     */
    @Override
    public boolean verifyNotifyResult(WxPayOrderNotifyResult orderNotifyResult, String xmlData) {
        try {
            if (!orderNotifyResult.getResultCode().equals("SUCCESS")) {
                // 支付失败，记录流水失败
                logger.error("支付失败");
                return false;
            } else {
                CarRmonOrder query = carRmonOrderMapper
                        .selectOne(new QueryWrapper<CarRmonOrder>().eq("order_id", orderNotifyResult.getOutTradeNo()));
                logger.info(String.format("{%s}", orderNotifyResult));
                if (!(WXPayUtil.isSignatureValid(xmlData, key))) {
                    logger.error("微信支付失败，失败原因：签名不通过");
                    return false;
                }
                if (query == null) {
                    logger.error("微信支付失败，失败原因：未找到相应的订单号");
                    return false;
                } else {

                    if (query.getPaymentResult().equals("1")) {
                        return false;
                    }

                    if (redisUtil.containsValueKey(orderNotifyResult.getOutTradeNo())) {
                        return false;
                    } else {
                        redisUtil.cacheValue(orderNotifyResult.getOutTradeNo(), "-rmon");
                    }

//                    if (wxPayCache.contains(orderNotifyResult.getOutTradeNo())) {
//                        return false;
//                    } else {
//                        wxPayCache.add(orderNotifyResult.getOutTradeNo());
//                        if (wxPayCache.size() > 1000) {
//                            wxPayCache.remove(0);
//                        }
//                    }

                    // 业务一：更新订单表
                    query.setTransactionId(orderNotifyResult.getTransactionId());
                    query.setOpenid(orderNotifyResult.getOpenid());
                    query.setUpdateTime(DateUtils.getNowDate());
                    query.setPaymentResult("1");
                    int update = carRmonOrderMapper.updateById(query);
                    if (update > 0) {
                        CarDevice carDevice = carDeviceMapper
                                .selectOne(new QueryWrapper<CarDevice>().eq("device_id", query.getDeviceId()));
                        carDevice.setDeviceRmon(1);
                        if (carDevice.getDmonEndTime() != null) {
                            String renew = addDmonExpireTime(carDevice.getDmonEndTime());
                            // 续费
                            carDevice.setDmonEndTime(DateUtils.parseDate(renew));
                        } else {
                            carDevice.setDmonEndTime(DateUtils.parseDate(getDmonExpireTime()));
                        }

                        int resultEdit = carDeviceMapper.updateById(carDevice);
                        if (resultEdit <= 0) {
                            logger.warn("购买远程监控服务失败！");
                            return false;
                        }

                        // 业务2：设置鑫钥授权
                        String clientId = query.getDeviceId();
                        String path = xinyaoServiceUrl + "/service/open";
                        Map<String, String> params = new HashMap<>();
                        params.put("clientId", clientId);
                        params.put("featureGroup", "rmon");
                        params.put("featureName", "rmon");
                        params.put("term", "12");
                        List<NameValuePair> paramsList = HttpClientUtil.getParams(params);
                        JSONObject http = HttpClientUtil.sendPost(path, paramsList, null);
                        if (http.getString("status").equals("200")) {
                            logger.info("开通服务授权成功！");
                        } else {
                            logger.warn("开通服务授权失败！");
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(String.format("未知错误：[%s]", e.getMessage()));
            return false;
        }
        return false;
    }

    @Override
    public JSONObject compareQRcodeTime(String deviceId) {
        List<CarRmonOrder> carOrders = carRmonOrderMapper
                .selectList(new QueryWrapper<CarRmonOrder>().eq("device_id", deviceId));
        JSONObject result = new JSONObject();
        if (carOrders == null) {
            return result;
        }
        for (CarRmonOrder order : carOrders) {
            if (DateUtils.compareDate(order.getTimeEnd())) {
                if (order.getPaymentResult().equals("1")) {
                    return result;
                }
                result.put("url", order.getQrcodeUrl());
                result.put("prepayId", order.getPrepayId());
                return result;
            }
            if (!(order.getPaymentResult().equals("1"))) {
                carRmonOrderMapper.deleteById(order);
            }
        }
        return result;
    }

    @Override
    public JSONObject registerProvider(String deviceId, String mobile, String password, String code) throws Exception {
        JSONObject result = new JSONObject();
        // 注册
        String path = URL + "auth/register";
        Map<String, String> params = new HashMap<>();
        params.put("mobile", mobile);
        params.put("password", password);
        params.put("code", code);
        List<NameValuePair> paramsList = HttpClientUtil.getParams(params);
        com.alibaba.fastjson.JSONObject http = HttpClientUtil.sendPost(path, paramsList, null);
        result.put("result", http);
        if (http.getString("status").equals("200")) {
            CarDevice carDevice = carDeviceMapper.selectOne(new QueryWrapper<CarDevice>().eq("device_id", deviceId));
            carDevice.setMobile(mobile);
            carDeviceMapper.updateById(carDevice);
        }
        return result;
    }

    @Override
    public JSONObject editPwdProvider(String deviceId, String mobile, String password, String code) throws Exception {
        String path = URL + "auth/sms";
        Map<String, String> appParams = new HashMap<>();
        appParams.put("mobile", mobile);
        appParams.put("code", code);
        List<NameValuePair> paramsList = HttpClientUtil.getParams(appParams);
        // http头封装token
        String token = HttpClientUtil.sendPost(path, paramsList, null).getString("result");
        String tokenPath = URL + "password/change";
        Map<String, String> tokenParams = new HashMap<>();
        tokenParams.put("oldPassword", mobile);
        tokenParams.put("newPassword", password);
        List<NameValuePair> tokenParamsList = HttpClientUtil.getParams(tokenParams);
        return HttpClientUtil.sendPost(tokenPath, tokenParamsList, token);

    }

    @Override
    public JSONObject resetPwdProvider(String deviceId, String mobile, String password, String code) throws Exception {
        JSONObject result = new JSONObject();
        String path = URL + "password/reset";
        Map<String, String> params = new HashMap<>();
        params.put("mobile", mobile);
        params.put("password", password);
        params.put("code", code);
        List<NameValuePair> paramsList = HttpClientUtil.getParams(params);
        com.alibaba.fastjson.JSONObject http = HttpClientUtil.sendPost(path, paramsList, null);
        result.put("result", http);
        if (http.getString("status").equals("200")) {
            CarDevice carDevice = carDeviceMapper.selectOne(new QueryWrapper<CarDevice>().eq("device_id", deviceId));
            carDevice.setMobile(mobile);
            carDeviceMapper.updateById(carDevice);
        }
        return result;
    }

    @Override
    public Date startServiceTime(String deviceId) {
        return carRmonOrderMapper.selectByTime(deviceId);
    }

    private static String getDmonExpireTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Calendar calendar = Calendar.getInstance();
        Date now = new Date();
        calendar.setTime(now);
        calendar.add(Calendar.YEAR, 1);
        return sdf.format(calendar.getTime());
    }

    private static String addDmonExpireTime(Date expire) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(expire);
        calendar.add(Calendar.YEAR, 1);
        return sdf.format(calendar.getTime());
    }

    private String getFullPathImgFtp() {
        if (ftpCatalog == null || ftpCatalog.equals("")) {
            return "ftp://" + ftpHost.concat("/" + imgTargetDir + "/");
        }
        return "ftp://" + ftpHost.concat("/" + ftpCatalog + "/" + imgTargetDir + "/");
    }

    @Override
    public XSSFWorkbook downloadRecorder() {
        List<CarRmonOrder> carRmonOrders = carRmonOrderMapper.selectList(null);
        XSSFWorkbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("car_rmon_order");
        Row titleRow = sheet.createRow(0);
        titleRow.createCell(1).setCellValue("订单序号");
        titleRow.createCell(2).setCellValue("设备序号");
        titleRow.createCell(3).setCellValue("回调url");
        titleRow.createCell(4).setCellValue("支付结果");
        titleRow.createCell(5).setCellValue("openId");
        titleRow.createCell(6).setCellValue("总价格");
        int cell = 1;
        for (CarRmonOrder carRmonOrder : carRmonOrders) {
            Row row = sheet.createRow(cell);
            row.createCell(0).setCellValue(cell);
            row.createCell(1).setCellValue(carRmonOrder.getOrderId());
            row.createCell(2).setCellValue(carRmonOrder.getDeviceId());
            row.createCell(3).setCellValue(carRmonOrder.getQrcodeUrl());
            row.createCell(4).setCellValue(carRmonOrder.getPaymentResult());
            row.createCell(5).setCellValue(carRmonOrder.getOpenid());
            row.createCell(6).setCellValue(carRmonOrder.getTotalPrice());
            cell++;
        }
        return wb;
    }

    @Override
    public boolean test(String num) {
        if (redisUtil.containsValueKey(num)) {
            return true;
        } else {
            redisUtil.cacheValue(num, "-rmon");
            return false;
        }
    }
}
